Credential Offer Callback
The credential offer callback is invoked when a credential offer is received by the agent. Its primary role is to display a user interface modal where the user can review the offered credentials and decide to accept or reject them. In addition, it handles UI template retrieval, dispatches Redux actions to update the application state, and provides a mechanism for additional details via a popup.
Key Features
-
Dynamic UI Strings:
Generates a title and detailed description based on the credentials offered. -
UI Template Retrieval:
Iterates over each credential to retrieve its corresponding UI template for enhanced presentation. -
User Interaction Modal:
Displays a modal with options (e.g., Accept/Reject) and a details popup for extra information.
Generic Implementation
Below is a more generic version of the credential offer callback. This implementation is designed to be easily customizable for developers, allowing you to adapt UI strings, button actions, and additional logic as needed.
credentialOfferCallback: async (credentialOffer) => {
// Generate basic UI strings
const title = 'Credential Offer';
const details = getCredentialLabelsString(credentialOffer.credentials);
const acceptCaption = credentialOffer.credentials.length === 1 ? 'Accept' : 'Accept All';
const rejectCaption = credentialOffer.credentials.length === 1 ? 'Reject' : 'Reject All';
// Ensure the agent is initialized and a connection exists
if (!agentInstance) {
console.error('Agent not initialized');
return { action: CredentialOfferCallbackAction.Later };
}
const connection = await agentInstance.contactManager.getHome();
if (!connection.result) {
console.error('Connection not found');
return { action: CredentialOfferCallbackAction.Later };
}
return new Promise(async (resolve) => {
// Prepare dictionaries for UI templates, attributes, and titles
const htmlContentDict = new Map();
const attributesDict = new Map();
const titles = new Map();
// Retrieve UI templates and collect credential information
for (const credential of credentialOffer.credentials) {
const { _namespace, _label } = credential.attributes;
const _schemaId = credential.schemaId;
console.log('Processing credential:', _namespace, _schemaId, _label);
let htmlContent = '';
const result = await agentInstance.credentialManager.getUITemplate(connection.result.id, _schemaId, _namespace);
if (result.isSuccessful && result.result) {
htmlContent = result.result;
} else {
console.log(`Failed to retrieve UI template for ${connection.result.id}: ${result.error}`);
}
htmlContentDict.set(credential.id, htmlContent);
attributesDict.set(credential.id, credential.attributes);
titles.set(credential.id, _label);
}
// Convert maps to plain objects for UI consumption
const plainAttributes = Object.fromEntries(attributesDict);
const plainHtmlContents = Object.fromEntries(htmlContentDict);
const plainTitles = Object.fromEntries(titles);
if (attributesDict.size === 0) {
console.log('No credential attributes available.');
return resolve({ action: CredentialOfferCallbackAction.Later });
}
// Navigate to a credential offer modal screen for example and pass to it the above data
RootNavigation.navigate(ScreenRoutesEnum.CREDENTIAL_OFFER_POPUP, {
title,
details,
titles: plainTitles,
titleBadge: credentialOffer.contact.logoUrl,
image: credentialOffer.contact.logoUrl,
contact: credentialOffer.contact,
credentials: credentialOffer.credentials,
htmlContents: plainHtmlContents,
primaryButton: {
caption: acceptCaption,
onPress: async () => {
resolve({ action: CredentialOfferCallbackAction.Accept });
await delay(200);
RootNavigation.goBack();
},
},
secondaryButton: {
caption: rejectCaption,
onPress: async () => {
resolve({ action: CredentialOfferCallbackAction.Reject });
await delay(200);
RootNavigation.goBack();
},
},
detailsPopup: {
buttonCaption: translate('action_view_extra_details'),
title: translate('view_extra_details'),
details: getCredentialAttributesString(credentialOffer.credentials),
},
onClose: async () => {
resolve({ action: CredentialOfferCallbackAction.Later });
await delay(200);
RootNavigation.goBack();
},
});
});
},
Explanation
-
Initialization Checks:
The function begins by verifying that the agent is initialized and that a valid connection exists. If not, it logs an error and defers further processing. -
UI Template Collection:
It iterates over each credential in the offer, retrieving the corresponding UI template via thegetUITemplate
method. The UI templates, along with other credential data, are stored in maps and later converted to plain objects for use in the modal. -
Modal Navigation:
The function navigates to a dedicated modal screen (CREDENTIAL_OFFER_POPUP
), passing along all the necessary data including credentials, UI templates, and custom button actions. -
User Decision Handling:
The modal provides buttons for accepting or rejecting the credential offer. Depending on the user's action, the promise is resolved with the appropriate action.. -
Customization:
Developers can easily modify UI strings, button captions, and additional logic within this generic implementation to better suit their specific application needs.
This provide a clear understanding of the function's purpose, its internal workings, and how to adapt it for your application's requirements.